package com.feijie.thread_demo.ThreadPool.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @program: thread_demo
 * @description: 测试多线程异步方法
 * @author: 作者
 * @create: 2022-03-08 09:12
 */
@Service
public class AsyncService {


    /**
     * 实际操作中，使用锁的思想为：将锁的对象指定为同一组对象信息，如车票中同一趟列车的列车号即为锁的对象，防止一列车中的数据脏读。不同的列车车票售卖线程可同时进行。
     *
     * 可使用缓存机制进行存锁，将请求中的车票信息放入缓存中，当请求进来时进行判断，若缓存中有该车票信息相对应的锁，则取出锁进行线程保护。
     *
     * 若车票信息不存在，则新建车票信息对应的锁。
     */
    static int tickets = 10;

    @Async
    public void synMethod() {

        System.out.println("开始");
        System.out.println(Thread.currentThread().getName());

        synchronized (this) {
            System.out.println(this.getClass().hashCode());

            if (tickets <= 0) {
                return;
            }

            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + "---->售出第 " + tickets + " 票 ");
            tickets--;
            System.out.println("结束");
        }
    }

    @Async
    public void synMethodByTicketNo(String ticketNo) {

        /**
         * 将锁放入缓存中，使用时进行比较。现没看到比较好的解决方案。。。。
         */

        System.out.println(ticketNo+"=>开始");

//        System.out.println(Thread.currentThread().getName());

        synchronized (ticketNo) {
            System.out.println(this.getClass().hashCode());

            if (tickets <= 0) {
                return;
            }

            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + "---->售出第 " + tickets + " 票 ");
            tickets--;
            System.out.println("结束");
        }
    }

    @Async
    public void method() {
        System.out.println("开始");
        System.out.println(Thread.currentThread().getName());


//        System.out.println(this.getClass().hashCode());

//        if (tickets <= 0) {
//            return;
//        }

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName() + "---->售出第 " + tickets + " 票 ");
        tickets--;
        System.out.println("结束");

    }


}
